home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 February / EnigmA AMIGA RUN 04 (1996)(G.R. Edizioni)(IT)[!][issue 1996-02][Skylink CD III].iso / earcd / util1 / yk211src.lha / Yak_2.11_Src / WBStartup / Hotkey_actions.c < prev    next >
C/C++ Source or Header  |  1995-10-18  |  29KB  |  1,344 lines

  1.  
  2. #define __USE_SYSBASE
  3.  
  4.  
  5. #include <proto/exec.h>
  6. #include <proto/dos.h>
  7. #include <proto/graphics.h>
  8. #include <proto/intuition.h>
  9. #include <proto/commodities.h>
  10. #include <proto/locale.h>
  11. #include <proto/reqtools.h>
  12.  
  13. #include <clib/alib_protos.h>
  14.  
  15. #include <exec/types.h>
  16. #include <exec/tasks.h>
  17. #include <dos/dostags.h>
  18. #include <dos/datetime.h>
  19. #include <intuition/intuitionbase.h>
  20. #include <libraries/locale.h>
  21. #include <libraries/reqtools.h>
  22.  
  23. #include <string.h>
  24.  
  25. #include "code.h"
  26. #include "yak.h"
  27. #include "hotkey_types.h"
  28. #include "Handlers.h"
  29. #include "Settings.h"
  30. #include "Requesters.h"
  31. #include "GetScreenBox.h"
  32. #include "GetPubScreen.h"
  33. #include "Arexx.h"
  34. #include "LastActiveWindow.h"
  35.  
  36. #ifndef USE_WB2CLI
  37. #  include "wbpath.h"
  38. #endif
  39.  
  40. #define CATCOMP_NUMBERS
  41. #include "yak_locale_strings.h"
  42.  
  43. IMPORT BOOL ShowYakInterface (VOID);
  44.  
  45. static void __regargs YakMoveScreen(struct Screen *scr, UWORD flags);
  46. static void __regargs EnlargeWindow(struct Window *win, UWORD flags);
  47. static void ChangeScreen(YakOption *opt);
  48. static struct Window *SelectWindow(YakOption *opt);
  49. static struct Screen *SelectScreen(YakOption *opt);
  50. static SAVEDS ASM void putcharfunc( REG(a0) struct Hook *h,
  51.                                     REG(a2) void *object,
  52.                                     REG(a1) char c);
  53. static struct InputEvent *FlipIEvents(struct InputEvent *);
  54. static int AddToStream(char *str, UBYTE delay); 
  55. static struct Window * FindWBWindow(void);
  56. static SAVEDS void  DoPalette(void);
  57. static int palette_count;
  58. static LONG beginCommand(char *command, LONG stack, LONG Priority);
  59. static struct Window *ActiveWindow(void);
  60. static struct Screen *ActiveScreen(void);
  61.  
  62.  
  63. extern struct WBStartup *WBMsg;
  64.  
  65.  
  66. /* okay to quit? (not so if palettes open) */
  67. int
  68. OkayToExit()
  69. {
  70.     return (palette_count == 0);
  71. }
  72.  
  73.  
  74. /* hook-function for inserting chars into input-stream */
  75. static SAVEDS ASM void 
  76. putcharfunc(REG(a0) struct Hook *h,
  77.             REG(a2) void *object,
  78.             REG(a1) char c)
  79. {
  80.     struct InputEvent ev;
  81.  
  82.     if (c)                      /* stop at null-terminator */
  83.     {
  84.         ev.ie_NextEvent = NULL;
  85.         InvertKeyMap(c, &ev, NULL);
  86.         AddIEvents(&ev);
  87.     }
  88. }
  89. /* and its associated structure */
  90. static struct Hook putcharhook = {
  91.         {NULL, NULL},
  92.         (APTR)putcharfunc,
  93.         NULL,
  94.         NULL
  95. };
  96.  
  97. /* given a list of input events, reverse their order */
  98. /* NB: the list BETTER terminate... */
  99. static struct InputEvent *
  100. FlipIEvents(struct InputEvent *ie)
  101. {
  102.     struct InputEvent *oldtail, *newtail = NULL;
  103.  
  104.     while (ie)
  105.     {
  106.         /* remove head, set next event */
  107.         oldtail = ie->ie_NextEvent; /* this will be prev event */
  108.         ie->ie_NextEvent = newtail; /* add to head */
  109.         newtail = ie;
  110.         ie = oldtail;           /* what's left */
  111.     }
  112.     return newtail;
  113. }
  114.  
  115. /* adds a string to the input-stream */
  116.  
  117. static int
  118. AddToStream(char *str, UBYTE delay)
  119. {
  120.     struct InputEvent *ie;
  121.  
  122.     if (ie = InvertString(str, NULL))
  123.     {
  124.         ie = FlipIEvents(ie);
  125.  
  126.         if (delay>0)
  127.         {
  128.             struct InputEvent *next;
  129.             while (ie)
  130.             {
  131.                 next = ie->ie_NextEvent; 
  132.                 ie->ie_NextEvent = NULL;
  133.                 AddIEvents(ie);
  134.                 FreeIEvents(ie);
  135.  
  136.                 Delay(delay);
  137.  
  138.                 ie = next;
  139.             }
  140.  
  141.         }
  142.         else
  143.         {
  144.             AddIEvents(ie);
  145.             FreeIEvents(ie);
  146.         }
  147.         return TRUE;
  148.     }
  149.     return FALSE;
  150. }
  151.  
  152. /* find (a) Workbench window */
  153. static struct Window *
  154. FindWBWindow()
  155. {
  156.     struct Screen *s = LockPubScreen("Workbench");
  157.     if (s)
  158.     {
  159.         struct Window *w = s->FirstWindow;
  160.         WBenchToFront();
  161.         Forbid();
  162.         for (; w; w = w->NextWindow)
  163.             if (w->Flags & WFLG_WBENCHWINDOW)
  164.                 break;
  165.         Permit();
  166.         UnlockPubScreen(NULL, s);
  167.         return w;
  168.     }
  169.     return NULL;
  170. }
  171.  
  172. /* bring a palette up on screen */
  173. /* CreateNewProc this function... */
  174. static SAVEDS void
  175. DoPalette()
  176. {
  177.     struct ReqToolsBase *ReqToolsBase;
  178.     struct Screen       *mousescr;
  179.     struct Window       *win;
  180.     STRPTR               title=getString(Palette_Title);
  181.     LONG                 tags[3];
  182.  
  183.     if (ReqToolsBase = (void *)OpenLibrary("reqtools.library", 0L))
  184.     {
  185.         mousescr = ReqToolsBase->IntuitionBase->FirstScreen;
  186.  
  187.         win=mousescr->FirstWindow;
  188.  
  189.         while (win)
  190.         {
  191.             if ((win->Title) && !strcmp(title, win->Title))
  192.             {
  193.                 WindowToFront(win);
  194.                 ActivateWindow(win);
  195.                 return;
  196.             }
  197.             win=win->NextWindow;
  198.         }
  199.  
  200.         palette_count++;
  201.  
  202.         tags[0] = RT_Screen;
  203.         tags[1] = (LONG)mousescr;
  204.         tags[2] = TAG_DONE;
  205.         (void) rtPaletteRequestA(title, NULL, (struct TagItem *)tags);
  206.         CloseLibrary((struct Library *)ReqToolsBase);
  207.     }
  208.     palette_count--;
  209. }
  210.  
  211. /*
  212.  * Asynchronous external command started with its own autocon Input/Output
  213.  * Result will only reflect whether System() call itself succeeded.
  214.  * If System() call fails, result will be -1L; -2L for window failure.
  215.  * We are using -2L as result if our Open of CON: fails
  216.  */
  217. #define AUTOCON "CON:0/25/640/150/Yak Command/AUTO/CLOSE/WAIT/ALT0/25/80/50"
  218. static LONG
  219. beginCommand(char *command, LONG Stack, LONG Priority)
  220. {
  221.     static ULONG stags[] = {
  222.         SYS_Input, NULL,
  223.         SYS_Output, NULL,
  224.         SYS_Asynch, TRUE,
  225.         SYS_UserShell, TRUE,
  226.         NP_Priority, 0L,
  227.         NP_StackSize, 4000L,
  228. #ifndef USE_WB2CLI
  229.         NP_Path, 0L,
  230. #endif
  231.         TAG_DONE
  232.         };
  233.     BPTR file;
  234.     char *filename;
  235.  
  236. #ifdef NOTDEF                   /* will this screw up sometimes? */
  237.     char *t;
  238.     int inquote = FALSE, usecon = TRUE;
  239.  
  240.     /* determine (simple-mindedly) whether there's redirection */
  241.     for (t = command; *t; t++)
  242.     {
  243.         if (*t == '\"')
  244.             if (t <= command || t[-1] != '*')
  245.                 inquote ^= 1;
  246.         if (!inquote)
  247.             if (*t == '>')
  248.             {
  249.                 usecon = FALSE;
  250.                 break;
  251.             }
  252.     }
  253.  
  254.     filename = usecon ? AUTOCON : "NIL:";
  255. #else
  256.     filename = AUTOCON;
  257. #endif
  258.     if (file = Open(filename, MODE_OLDFILE))
  259.     {
  260.         stags[1] = (ULONG)file;
  261.         stags[9] = Priority;
  262.         
  263.         if (Stack>0)
  264.         {
  265.             stags[11] = Stack;
  266.         }
  267.  
  268. #ifndef USE_WB2CLI
  269.         if (WBMsg)
  270.         {
  271.             stags[13] = (ULONG) CloneWorkbenchPath(WBMsg); 
  272.         }
  273. #endif
  274.         return(SystemTagList(command, (struct TagItem *)stags));
  275.     }
  276.     else return(-2);
  277. }
  278.  
  279.  
  280. /* execute a command */
  281. void
  282. act_ExecuteCommand(YakHotKey *yhk)
  283. {
  284.     LONG rc;
  285.  
  286.     if (yhk->yhk_Option[1].ArgStr[0])
  287.     {
  288.         ChangeScreen(&yhk->yhk_Option[0]);
  289.  
  290.         if (yhk->yhk_Option[1].Flags & HKO_CLI_COMMAND)
  291.         {
  292.             rc = beginCommand(yhk->yhk_Option[1].ArgStr[0], 
  293.                               yhk->yhk_Option[1].ArgNum[0], 
  294.                               yhk->yhk_Option[1].ArgNum[1]);
  295.         }
  296.         else
  297.         {
  298.             rc = SendARexxCommand(yhk->yhk_Option[1].ArgStr[1], yhk->yhk_Option[1].ArgStr[0]);
  299.         }
  300.         if (rc != 0)
  301.             PostError("%s\n\"%s\"",
  302.                       getString(Couldnt_execute_command_ERR), 
  303.                       yhk->yhk_Option[1].ArgStr[0]);
  304.     }
  305.     else 
  306.         PostError("%s\"%s\".", 
  307.                   getString(No_cmd_specified_for_hotkey_ERR), 
  308.                   yhk->yhk_KeyDef);
  309. }
  310.  
  311.  
  312. void
  313. act_CloseWindow(YakHotKey *yhk)
  314. {
  315.         /* CloseEvent is declared as static to save some bytes and speed up code */
  316.     static struct InputEvent CloseEvent = { NULL, IECLASS_CLOSEWINDOW, 0, 0, 0, 0 };
  317.     struct Window *window;
  318.     struct Window *CurrentWindow = NULL;
  319.  
  320.     CurrentWindow = ActiveWindow();
  321.  
  322.     if (window = SelectWindow(&yhk->yhk_Option[0]))
  323.     {
  324.         if (window && (window->Flags & CLOSEGADGET))
  325.         {
  326.             ActivateWindow(window);
  327.             AddIEvents(&CloseEvent);
  328.  
  329.             do 
  330.             {
  331.                 Delay(1);
  332.             } while (window == ActiveWindow());
  333.  
  334.             if (CurrentWindow && (window != CurrentWindow))
  335.             {
  336.                 ActivateWindow(CurrentWindow);
  337.             }
  338.             else
  339.             {   
  340.                 if (autopoint)
  341.                 {
  342.                     ActivateMouseWindow (KEY);
  343.                 }
  344.             }
  345.         }
  346.     }
  347. }
  348.  
  349.  
  350.  
  351. /*
  352.  * This function simulates Intuition mutal exclusion for menu items.
  353.  */ 
  354.  
  355. static __regargs void
  356. UnCheckExcludedItems(UWORD  menu, 
  357.                      UWORD  item, 
  358.                      UWORD  sub, 
  359.                      ULONG MutualExclude, 
  360.                      struct Window *window)
  361. {
  362.     struct MenuItem *menuitem;
  363.     UWORD  menuNumber;
  364.     UBYTE  i=0;
  365.  
  366.     while (MutualExclude > 0)
  367.     {
  368.         if (MutualExclude & 1)
  369.         {
  370.             /* Item to exclude */
  371.  
  372.             if (sub == NOSUB)
  373.             {
  374.                 item = i;
  375.             }
  376.             else
  377.             {
  378.                 sub = i;
  379.             }
  380.  
  381.             menuNumber = FULLMENUNUM( menu, item, sub );
  382.             menuitem = ItemAddress(window->MenuStrip, menuNumber);
  383.  
  384.             if ((menuitem) &&                       /* item must exist      */
  385.                 (menuitem->Flags & ITEMENABLED) && /* item must be enabled */
  386.                 (menuitem->Flags & CHECKED))       /* item must be checked */
  387.             {
  388.                 menuitem->Flags &= ~CHECKED;
  389.             }
  390.         }
  391.         MutualExclude = MutualExclude >> 1;
  392.         i++;
  393.     }
  394. }
  395.  
  396.  
  397. void
  398. act_MenuShortcut(YakHotKey *yhk)
  399. {
  400.     /* MenuEvent is declared as static to save some bytes and speed up code */
  401.     static struct InputEvent MenuEvent = { NULL, IECLASS_MENULIST, 0, 0, IEQUALIFIER_LEFTBUTTON, 0 };
  402.     struct Window *window;
  403.     struct MenuItem *menuitem;
  404.     UWORD  menuNumber, menu, item, sub;
  405.  
  406.     window = ActiveWindow();
  407.  
  408.     menu = (UWORD) yhk->yhk_Option[0].ArgNum[0];
  409.     item = (UWORD) yhk->yhk_Option[0].ArgNum[1];
  410.  
  411.     if (yhk->yhk_Option[0].Flags & HKO_SUBITEM)
  412.     {
  413.         sub = (UWORD) yhk->yhk_Option[0].ArgNum[2];
  414.     }
  415.     else
  416.     {
  417.         /* no subitem specified */
  418.         sub = NOSUB;
  419.     }
  420.  
  421.     if (window && (window->MenuStrip))
  422.     {
  423.         menuNumber = FULLMENUNUM( menu, item, sub );
  424.         menuitem = ItemAddress(window->MenuStrip, menuNumber);
  425.  
  426.         if ((menuitem) &&                     /* item must exist             */
  427.             (menuitem->Flags & ITEMENABLED)) /* item must be enabled        */
  428.         {
  429.             /* We don't want multi selection */
  430.             menuitem->NextSelect = MENUNULL;
  431.  
  432.             /* Take care of checkit items */
  433.             if (menuitem->Flags & CHECKIT)
  434.             {
  435.                 if (menuitem->Flags & MENUTOGGLE) 
  436.                 {
  437.                     if (menuitem->Flags & CHECKED)
  438.                     {
  439.                         /* If it's already checked, uncheck it */
  440.                         menuitem->Flags &= ~CHECKED;
  441.                     }
  442.                     else
  443.                      {
  444.                         /* If it's unchecked, check it */
  445.                         menuitem->Flags |= CHECKED;
  446.                     }
  447.                 }
  448.                 else 
  449.                 {
  450.                     /* Mutual Exclude */
  451.                     if ((menuitem->Flags & CHECKED) == FALSE)
  452.                     {
  453.                         /* check it */
  454.                         menuitem->Flags |= CHECKED;
  455.  
  456.                         /* and then take care of excluded items */
  457.                         UnCheckExcludedItems(menu, item, sub, menuitem->MutualExclude, window);
  458.                     }
  459.                 }
  460.             }
  461.  
  462.             /* Send our event */
  463.             MenuEvent.ie_Code         = menuNumber;
  464.             MenuEvent.ie_EventAddress = window;
  465.  
  466.             AddIEvents(&MenuEvent);
  467.         }
  468.     }
  469.  
  470. }
  471.  
  472. void
  473. act_ZipWindow(YakHotKey *yhk)
  474. {
  475.     struct Window *window;
  476.     ULONG lock;
  477.  
  478.     lock = LockIBase(0);
  479.     if (window = SelectWindow(&yhk->yhk_Option[0]))
  480.     {
  481.         if (window->Flags & WFLG_HASZOOM)
  482.             ZipWindow(window);
  483.     }
  484.     UnlockIBase(lock);
  485. }
  486.  
  487. void
  488. act_ShrinkWindow(YakHotKey *yhk)
  489. {
  490.     struct Window *window;
  491.     ULONG lock;
  492.  
  493.     lock = LockIBase(0);
  494.     if (window = SelectWindow(&yhk->yhk_Option[0]))
  495.     {
  496.         if (window->Flags & WFLG_SIZEGADGET)
  497.             ChangeWindowBox(window,
  498.                             window->LeftEdge,
  499.                             window->TopEdge,
  500.                             window->MinWidth,
  501.                             window->MinHeight);
  502.     }
  503.     UnlockIBase(lock);
  504. }
  505.  
  506. void
  507. act_ExpandWindow(YakHotKey *yhk)
  508. {
  509.     struct Window  *win;
  510.     ULONG           lock;
  511.  
  512.     lock = LockIBase(0);
  513.  
  514.     if (win = SelectWindow(&yhk->yhk_Option[0]))
  515.     {
  516.         if (win->Flags & WFLG_SIZEGADGET)
  517.         {
  518.             EnlargeWindow(win, yhk->yhk_Option[1].Flags);
  519.         }
  520.     }
  521.  
  522.     UnlockIBase(lock);
  523. }
  524.  
  525.  
  526. void
  527. act_MoveWindow(YakHotKey *yhk)
  528. {
  529.     struct Window  *win;
  530.     WORD            top, left,
  531.                     width, height;
  532.     ULONG           lock;
  533.     struct IBox     box;
  534.     struct Screen  *s;
  535.  
  536.     lock = LockIBase(0);
  537.  
  538.     if (win=SelectWindow(&yhk->yhk_Option[0]))
  539.     {
  540.  
  541.         if (win->Flags & WFLG_DRAGBAR)
  542.         {
  543.             top    = win->TopEdge;
  544.             left   = win->LeftEdge;
  545.             width  = win->Width;
  546.             height = win->Height;
  547.             s      = win->WScreen;
  548.  
  549.  
  550.             GetScreenBox(s, &box, (yhk->yhk_Option[1].Flags & HKO_MOVE_VISIBLE_BAR));
  551.  
  552.             if (yhk->yhk_Option[1].Flags & HKO_MOVE_LEFT)
  553.                 left = box.Left;
  554.  
  555.             if (yhk->yhk_Option[1].Flags & HKO_MOVE_HORIZONTAL_CENTER)
  556.                 left = box.Left + (box.Width-width)>>1;
  557.  
  558.             if (yhk->yhk_Option[1].Flags & HKO_MOVE_RIGHT)
  559.                 left = box.Left + box.Width - width;
  560.  
  561.             if (yhk->yhk_Option[1].Flags & HKO_MOVE_TOP)
  562.                 top = box.Top;
  563.  
  564.             if (yhk->yhk_Option[1].Flags & HKO_MOVE_VERTICAL_CENTER)
  565.                 top = box.Top + (box.Height-height)/2;
  566.  
  567.             if (yhk->yhk_Option[1].Flags & HKO_MOVE_BOTTOM)
  568.                 top = box.Top + box.Height - height;
  569.  
  570.             if (win->LeftEdge != left || win->TopEdge != top)
  571.                 ChangeWindowBox(win,
  572.                                 left,
  573.                                 top,
  574.                                 width,
  575.                                 height);
  576.  
  577.         }
  578.     }
  579.  
  580.     UnlockIBase(lock);
  581. }
  582.  
  583.  
  584. /*
  585.  * This function tells if a window has to be cycled according to 
  586.  * the cycling options
  587.  */
  588.  
  589. __regargs BOOL
  590. MatchWindow(struct Window *win, UWORD Options, STRPTR Pattern)
  591. {
  592.     BOOL result;
  593.     struct Task *WinTask;
  594.     STRPTR TaskName;
  595.  
  596.     if (win)
  597.     {
  598.         if (Options & HKO_EXCLUDE_WB_DRAWERS) 
  599.         {
  600.             result = !(win->Flags & WFLG_WBENCHWINDOW);
  601.         }
  602.         else
  603.         {
  604.             result = TRUE;
  605.         }
  606.    
  607.         if ((result==TRUE) && !(Options & HKO_ACTIVATE_ONLY)) 
  608.         {
  609.             result = !(win->Flags & WFLG_BACKDROP);
  610.         }
  611.  
  612.         if ((result==TRUE) && (Options & HKO_BY_WINDOW_TASK_NAME))
  613.         {
  614.             /* This is the task attached to our window */
  615.             if ((WinTask = win->UserPort->mp_SigTask) &&
  616.                 (TaskName = WinTask->tc_Node.ln_Name))
  617.             {
  618.                 /* Does its name match our pattern? */
  619.                 result = MatchPattern(Pattern, TaskName);
  620.             }
  621.             else
  622.             {
  623.                 result = FALSE;
  624.             }
  625.         }
  626.     }
  627.     else
  628.     {
  629.         result = FALSE;
  630.     }
  631.  
  632.     return(result);
  633. }
  634.  
  635.  
  636. /* This function cycle through specified windows 
  637.  * WARNING: it must be called under Forbid()/LockIBase()
  638.  */
  639. void
  640. SelectiveCycleWindows(struct Screen *s, 
  641.                       UWORD Options, 
  642.                       STRPTR Pattern)
  643. {
  644.     struct Layer  *l;
  645.     struct Window *curwin = NULL;
  646.     struct Window *next;
  647.     struct Window *backmost = NULL;
  648.    
  649.     if (l = s->LayerInfo.top_layer)
  650.     {
  651.         /* starting from top layer one, find backmost window 
  652.          * that matches our criterias
  653.          */
  654.         for (l = s->LayerInfo.top_layer; l; l = l->back)
  655.         {
  656.             curwin = (struct Window *)l->Window;
  657.             if (MatchWindow(curwin, Options, Pattern))
  658.                 backmost = curwin;
  659.         }   
  660.  
  661.         l = backmost->WLayer;
  662.  
  663.         if (Options & HKO_ACTIVATE_ONLY)
  664.         {
  665.             if ((IntuitionBase->ActiveWindow) &&
  666.                 (IntuitionBase->ActiveWindow->WScreen == s))
  667.             {
  668.                 curwin = IntuitionBase->ActiveWindow;
  669.             }                    
  670.             else
  671.             {
  672.                 curwin = s->FirstWindow;
  673.             }
  674.         }
  675.         else
  676.         {
  677.             curwin = backmost;
  678.         }
  679.  
  680.         if (curwin)
  681.         {
  682.             l = curwin->WLayer; 
  683.             next = curwin;
  684.  
  685.             if (Options & HKO_ACTIVATE_ONLY)
  686.             {
  687.                 while (l && 
  688.                        (!MatchWindow(next, Options, Pattern) ||
  689.                         (next == curwin)))
  690.                 {
  691.                     next = (struct Window *)l->Window;
  692.                     l = l->front;
  693.                 } 
  694.                 if (next == curwin)
  695.                 {
  696.                     /* We have reached TopLayer window, so go back to back most one */
  697.                     next = backmost;
  698.                 }
  699.             }
  700.             else
  701.             {
  702.                 while (l && 
  703.                        !MatchWindow(next, Options, Pattern))
  704.                 {
  705.                     next = (struct Window *)l->Window;
  706.                     l = l->front;
  707.                 } 
  708.                 ScreenToFront(next->WScreen);
  709.                 WindowToFront(next);
  710.             }
  711.             ActivateWindow(next);
  712.         }
  713.     }
  714. }
  715.  
  716.  
  717. /* 
  718.  * This function cycle through specified windows but in the inverse 
  719.  * direction as the one used by SelectiveCycleWindows().
  720.  * WARNING: it must be called under Forbid()/LockIBase()
  721.  * 
  722.  */
  723.  
  724. void
  725. SelectiveBackCycleWindows(struct Screen *s, 
  726.                           UWORD Options, 
  727.                           STRPTR Pattern)
  728. {
  729.     struct Layer  *l;
  730.     struct Window *frontmost;
  731.     struct Window *previous;
  732.     struct Window *curwin = NULL;
  733.    
  734.     if (l = s->LayerInfo.top_layer)
  735.     {
  736.         /* starting from top layer one, find frontmost window that matches
  737.          * our criterias.
  738.          */
  739.         frontmost = NULL;
  740.  
  741.         while (l && !MatchWindow(frontmost, Options, Pattern))
  742.         {
  743.             frontmost = (struct Window *)l->Window;        
  744.             l = l->back;    
  745.         }
  746.  
  747.         if (frontmost)
  748.         {
  749.             if (Options & HKO_ACTIVATE_ONLY)
  750.             {
  751.                 if ((IntuitionBase->ActiveWindow) &&
  752.                     (IntuitionBase->ActiveWindow->WScreen == s))
  753.                 {
  754.                     curwin = IntuitionBase->ActiveWindow;
  755.                 }    
  756.                 else
  757.                 {
  758.                     curwin = s->FirstWindow;
  759.                 }
  760.             }
  761.             else
  762.             {
  763.                 curwin = frontmost;
  764.                 if (MatchWindow(curwin, Options, Pattern))
  765.                 {
  766.                     WindowToBack(curwin);
  767.                 }
  768.             }
  769.  
  770.             /* find the frontmost matching window by starting from the top layer 
  771.              * We must take care to exclude the window we start from.
  772.              */
  773.  
  774.  
  775.             l = curwin->WLayer;
  776.             previous = curwin;
  777.         
  778.             while (l && 
  779.                    (!MatchWindow(previous, Options, Pattern) ||
  780.                     (previous == curwin))) 
  781.             {
  782.                 previous = (struct Window *)l->Window;
  783.                 l = l->back;
  784.             } 
  785.  
  786.             if ((l == NULL) && ((previous == NULL) || (previous == curwin)))
  787.             {
  788.                 /* We have reached the backmost window.*/
  789.                 previous = frontmost;    
  790.             }
  791.  
  792.             if (!(Options & HKO_ACTIVATE_ONLY))
  793.             {
  794.                 WindowToFront(previous);
  795.             }
  796.             ActivateWindow(previous);
  797.         }
  798.     }
  799. }
  800.  
  801.  
  802. void
  803. act_CycleWindows(YakHotKey *yhk)
  804. {
  805.     struct Screen *s;
  806.     PatternData   pdata = {"",NULL};
  807.     ULONG lock;
  808.  
  809.     if (s = SelectScreen(&yhk->yhk_Option[0]))
  810.     {
  811.         if (yhk->yhk_Option[1].Flags & HKO_BY_WINDOW_TASK_NAME)
  812.         {
  813.             InitPattern(yhk->yhk_Option[1].ArgStr[0], &pdata);
  814.         }
  815.  
  816.         lock = LockIBase(0);
  817.         Forbid();
  818.  
  819.         if (yhk->yhk_Option[1].Flags & HKO_BACK_CYCLE) 
  820.         {
  821.             SelectiveBackCycleWindows(s, yhk->yhk_Option[1].Flags, pdata.pat);
  822.         } 
  823.         else
  824.         {
  825.             SelectiveCycleWindows(s, yhk->yhk_Option[1].Flags, pdata.pat);
  826.         }
  827.  
  828.         Permit();
  829.         UnlockIBase(lock);
  830.  
  831.         FreeVec(pdata.pat);
  832.     }
  833.  
  834. }    
  835.  
  836.  
  837. /* taglist for CreateNewProc */
  838. static LONG palette_taglist[] = {
  839.         NP_Entry, (LONG)DoPalette,
  840.         NP_Name, (LONG)"Yak Palette",
  841.         TAG_DONE
  842. };
  843.  
  844. void
  845. act_OpenPalette(YakHotKey *yhk)
  846. {
  847.     ChangeScreen(&yhk->yhk_Option[0]);
  848.  
  849.     CreateNewProc((struct TagItem *)palette_taglist);
  850. }
  851.  
  852. void
  853. act_ScreenToFront(YakHotKey *yhk)
  854. {
  855.     struct Screen *s;
  856.  
  857.     if (s=SelectScreen(&yhk->yhk_Option[0]))
  858.     {
  859.         MyScreenToFront(s);
  860.     }
  861. }
  862.  
  863. void
  864. act_ScreenToBack(YakHotKey *yhk)
  865. {
  866.     struct Screen *s;
  867.  
  868.     if (s=SelectScreen(&yhk->yhk_Option[0]))
  869.     {
  870.         MyScreenToBack(s);
  871.     }
  872. }
  873.  
  874. void
  875. act_ActivateWorkbench(YakHotKey *yhk)
  876. {
  877.     struct Window *w;
  878.  
  879.     if (w = FindWBWindow())
  880.     {
  881.         WBenchToFront();
  882.         ActivateWindow(w);
  883.     }
  884. }
  885.  
  886. void
  887. act_MoveScreen(YakHotKey *yhk)
  888. {
  889.     struct Screen *scr;
  890.  
  891.     if (scr = SelectScreen(&yhk->yhk_Option[0]))
  892.     {
  893.         YakMoveScreen(scr, yhk->yhk_Option[1].Flags);
  894.     }
  895. }
  896.  
  897. void
  898. act_BlankDisplay(YakHotKey *yhk)
  899. {
  900.     BlankScreen();
  901. }
  902.  
  903. void
  904. act_InsertText(YakHotKey *yhk)
  905. {
  906.     if (yhk->yhk_Option[0].ArgStr[0])
  907.     {
  908.         if (!AddToStream(yhk->yhk_Option[0].ArgStr[0], (UBYTE)yhk->yhk_Option[0].ArgNum[0]))
  909.             PostError("%s:\n \"%s\"", 
  910.                       getString(Text_insertion_str_invalid_ERR), yhk->yhk_Option[0].ArgStr[0]);
  911.     }
  912.     else PostError("%s \"%s\" %s", 
  913.                    getString(Yak_text_hotkey_ERR),
  914.                    yhk->yhk_KeyDef,
  915.                    getString(Has_no_text_specified_ERR));
  916. }
  917.  
  918. void
  919. act_InsertDate(YakHotKey *yhk)
  920. {
  921.     struct DateTime dat;
  922.     DateStamp(&dat.dat_Stamp);
  923.  
  924.     if (LocaleBase)
  925.     {
  926.         if (yhk->yhk_Option[0].ArgStr[0])
  927.             FormatDate(locale, yhk->yhk_Option[0].ArgStr[0], &dat.dat_Stamp, &putcharhook);
  928.         else PostError("%s \"%s\" %s", 
  929.                        getString(Yak_date_hotkey_ERR),
  930.                        yhk->yhk_KeyDef,
  931.                        getString(Has_no_format_specified_ERR));
  932.     }
  933.     else
  934.     {
  935.         /* pre-2.1 OS */
  936.         char datestr[LEN_DATSTRING];
  937.  
  938.         dat.dat_Format = FORMAT_DOS;
  939.         dat.dat_Flags = 0;
  940.         dat.dat_StrDate = datestr;
  941.         dat.dat_StrDay = dat.dat_StrTime = NULL;
  942.         DateToStr(&dat);
  943.         AddToStream(datestr, 0);
  944.     }
  945. }
  946.  
  947.  
  948. void
  949. act_ShowInterface(YakHotKey *yhk)
  950. {
  951.     ChangeScreen(&yhk->yhk_Option[0]);
  952.     ShowYakInterface();
  953. }
  954.  
  955.  
  956.  
  957. /* Set the active screen as default public screen if it a public screen 
  958. ** else do nothing.
  959. **/
  960. void
  961. act_CurrentScreenAsDefPub(YakHotKey *yhk)
  962. {
  963.     UBYTE *PSName;
  964.     struct Screen *s;
  965.  
  966.     /* Get the active screen */
  967.     s = ActiveScreen();
  968.  
  969.     /* Get the name of our screen if it is a public screen */
  970.     PSName = GetPubScreenName(s);
  971.  
  972.     if (PSName)
  973.     {
  974.         /* active screen is a public screen so 
  975.          * make it default public screen
  976.          */
  977.         SetDefaultPubScreen(PSName);
  978.     }
  979. }
  980.  
  981.  
  982.  
  983. static void __regargs
  984. YakMoveScreen(struct Screen *scr, UWORD flags)
  985. {
  986.     struct Window    *win;
  987.     struct Rectangle  rect;
  988.     struct IBox       b_box, f_box;
  989.     ULONG             modeid;
  990.     WORD              dx=0,dy=0;
  991.  
  992.     if ( (modeid = GetVPModeID(&scr->ViewPort)) != INVALID_ID &&
  993.          QueryOverscan(modeid, &rect, OSCAN_TEXT))
  994.     {
  995.         if((flags & HKO_MOVE_VISIBLE_BAR) &&
  996.            (win=ActiveWindow()) &&
  997.            (win->WScreen == scr))
  998.         {
  999.             GetScreenBox(scr, &b_box, FALSE);
  1000.             f_box.Left   = win->LeftEdge;
  1001.             f_box.Top    = win->TopEdge;
  1002.             f_box.Width  = win->Width;
  1003.             f_box.Height = win->Height;
  1004.         }
  1005.         else
  1006.         {
  1007.             b_box.Left   = rect.MinX;
  1008.             b_box.Top    = rect.MinY;
  1009.             b_box.Width  = rect.MaxX - rect.MinX + 1;
  1010.             b_box.Height = rect.MaxY - rect.MinY + 1;
  1011.             f_box.Left   = scr->LeftEdge;
  1012.             f_box.Top    = scr->TopEdge;
  1013.             f_box.Width  = scr->Width;
  1014.             f_box.Height = scr->Height;
  1015.         }
  1016.  
  1017.         if (flags & HKO_MOVE_LEFT)
  1018.             dx = b_box.Left - f_box.Left;
  1019.  
  1020.         if (flags & HKO_MOVE_HORIZONTAL_CENTER)
  1021.             dx = b_box.Left - f_box.Left + ((b_box.Width - f_box.Width) >> 1);
  1022.  
  1023.         if (flags & HKO_MOVE_RIGHT)
  1024.             dx = b_box.Left - f_box.Left + b_box.Width - f_box.Width;
  1025.  
  1026.         if (flags & HKO_MOVE_TOP)
  1027.             dy = b_box.Top - f_box.Top;
  1028.  
  1029.         if (flags & HKO_MOVE_VERTICAL_CENTER)
  1030.             dx = b_box.Top - f_box.Top + ((b_box.Height - f_box.Height) >> 1);
  1031.  
  1032.         if (flags & HKO_MOVE_BOTTOM)
  1033.             dy = b_box.Top - f_box.Top + b_box.Height - f_box.Height;
  1034.  
  1035.         MoveScreen(scr, dx, dy);
  1036.     }
  1037. }
  1038.  
  1039.  
  1040. static void __regargs
  1041. EnlargeWindow(struct Window *win, UWORD flags)
  1042. {
  1043.     WORD            width  = win->Width,
  1044.                     height = win->Height,
  1045.                     top    = win->TopEdge,
  1046.                     left   = win->LeftEdge,
  1047.                     l;
  1048.     struct IBox     box;
  1049.     struct Screen  *s = win->WScreen;
  1050.  
  1051.     GetScreenBox(s, &box, flags & HKO_RESIZE_VISIBLE_BAR);
  1052.  
  1053.     if (flags & HKO_RESIZE_HORIZONTAL)
  1054.     {
  1055.         width = win->MaxWidth;
  1056.         if (width == -1 || width > box.Width)
  1057.             width = box.Width;
  1058.         if (left < box.Left)
  1059.         {
  1060.             left = box.Left;
  1061.         } 
  1062.         else
  1063.         {
  1064.             if ((l = box.Left + box.Width - left - width) < 0)
  1065.                 left += l;
  1066.         }
  1067.     }
  1068.     if (flags & HKO_RESIZE_VERTICAL)
  1069.     {
  1070.         height = win->MaxHeight;
  1071.         if (height == -1 || height > box.Height)
  1072.             height = box.Height;
  1073.  
  1074.         if (top < box.Top)
  1075.         {
  1076.             top = box.Top;
  1077.         } else
  1078.         {
  1079.             if ((l = box.Top + box.Height - top - height) < 0)
  1080.                 top += l;
  1081.         }
  1082.     }
  1083.     if (win->LeftEdge != left || win->TopEdge != top ||
  1084.         win->Width != width || win->Height != height)
  1085.         ChangeWindowBox(win,
  1086.                         left,
  1087.                         top,
  1088.                         width,
  1089.                         height);
  1090. }
  1091.  
  1092.  
  1093.  
  1094. static struct Window *
  1095. ActiveWindow(void)
  1096. {
  1097.     ULONG lock;
  1098.     struct Window *window=NULL;
  1099.  
  1100.     lock = LockIBase(0);
  1101.     window = IntuitionBase->ActiveWindow;
  1102.     UnlockIBase(lock);
  1103.  
  1104.     return window;
  1105. }
  1106.  
  1107.  
  1108.  
  1109.  
  1110. static struct Window *
  1111. WindowByTitle(STRPTR title)
  1112. {
  1113.     struct Screen *screen      = NULL;
  1114.     struct Window *window      = NULL;
  1115.     BOOL           WindowFound = FALSE;
  1116.     PatternData    pdata       = {"",NULL};
  1117.  
  1118.     if (InitPattern(title, &pdata))
  1119.     {
  1120.         ULONG lock = LockIBase(0);
  1121.  
  1122.         screen = IntuitionBase->FirstScreen;
  1123.  
  1124.         while (screen && !WindowFound)
  1125.         {
  1126.             window = screen->FirstWindow;
  1127.  
  1128.             while (window && !WindowFound)
  1129.             {
  1130.                 if (window->Title)
  1131.                 {
  1132.                     WindowFound = MatchPattern(pdata.pat, window->Title);
  1133.                 }
  1134.                 if (WindowFound == FALSE)
  1135.                 {
  1136.                     window = window->NextWindow;
  1137.                 }
  1138.             }
  1139.             screen = screen->NextScreen;
  1140.         }
  1141.     
  1142.         UnlockIBase(lock);
  1143.  
  1144.         FreeVec(pdata.pat);
  1145.     }
  1146.     
  1147.     if (WindowFound)
  1148.     {
  1149.         return(window);
  1150.     }
  1151.     else
  1152.     {
  1153.         return(NULL);
  1154.     }
  1155. }
  1156.  
  1157.  
  1158. static struct Screen *
  1159. ActiveScreen(void)
  1160. {
  1161.     ULONG lock;
  1162.     struct Screen *screen=NULL;
  1163.   
  1164.     lock = LockIBase(0);
  1165.     screen = IntuitionBase->ActiveScreen;
  1166.     UnlockIBase(lock);
  1167.     
  1168.     return (screen);
  1169. }
  1170.  
  1171.  
  1172.  
  1173. static struct Screen *
  1174. ScreenByTitle(STRPTR title)
  1175. {
  1176.     struct Screen *screen      = NULL;
  1177.     PatternData    pdata       = {"",NULL};
  1178.     BOOL           ScreenFound = FALSE;
  1179.  
  1180.     if (InitPattern(title, &pdata))
  1181.     {
  1182.         ULONG lock = LockIBase(0);
  1183.  
  1184.         screen = IntuitionBase->FirstScreen;
  1185.  
  1186.         while (screen && !ScreenFound)
  1187.         {
  1188.             if (screen->DefaultTitle)
  1189.             {
  1190.                 ScreenFound=MatchPattern(pdata.pat, screen->DefaultTitle);
  1191.             }
  1192.             if (ScreenFound == FALSE) 
  1193.             {
  1194.                 screen = screen->NextScreen;
  1195.             }
  1196.         }
  1197.     
  1198.         UnlockIBase(lock);
  1199.  
  1200.         FreeVec(pdata.pat);
  1201.     }
  1202.     
  1203.     if (ScreenFound)
  1204.     {
  1205.         return(screen);
  1206.     }
  1207.     else
  1208.     {
  1209.         return(NULL);
  1210.  
  1211.     }
  1212. }
  1213.  
  1214. struct Screen *
  1215. RearmostScreen(void)
  1216. {
  1217.     ULONG lock;
  1218.     struct Screen *screen=NULL, *ns;
  1219.   
  1220.     lock = LockIBase(0);
  1221.    
  1222.     screen = IntuitionBase->FirstScreen;
  1223.  
  1224.     ns = screen->NextScreen;
  1225.     while (ns)
  1226.     {
  1227.         screen = ns;
  1228.         ns     = screen->NextScreen;
  1229.     }
  1230.  
  1231.     UnlockIBase(lock);
  1232.  
  1233.     return screen;
  1234. }
  1235.  
  1236.  
  1237. static struct Screen *
  1238. FrontmostScreen(void)
  1239. {
  1240.     ULONG lock;
  1241.     struct Screen *screen=NULL;
  1242.   
  1243.     lock = LockIBase(0);
  1244.     screen = IntuitionBase->FirstScreen;
  1245.     UnlockIBase(lock);
  1246.  
  1247.     return screen;
  1248. }
  1249.  
  1250.  
  1251. static struct Window *
  1252. SelectWindow(YakOption *opt)
  1253. {
  1254.     struct Window *window=NULL;
  1255.  
  1256.     switch (opt->Flags)
  1257.     {
  1258.         case HKO_ACTIVE:
  1259.             window = ActiveWindow();
  1260.             break;
  1261.  
  1262.         case HKO_UNDER_MOUSE:
  1263.             window = WindowUnderMouse();
  1264.             break;
  1265.  
  1266.         case HKO_BY_TITLE|HKO_PATTERN:
  1267.             window = WindowByTitle(opt->ArgStr[0]);
  1268.             break;
  1269.     }
  1270.     return window;
  1271. }
  1272.  
  1273.  
  1274. static struct Screen *
  1275. SelectScreen(YakOption *opt)
  1276. {
  1277.     struct Screen *screen=NULL;
  1278.  
  1279.     switch (opt->Flags)
  1280.     {
  1281.       case HKO_ACTIVE:
  1282.         screen = ActiveScreen();
  1283.         break;
  1284.  
  1285.       case HKO_UNDER_MOUSE:
  1286.         screen = ScreenUnderMouse();
  1287.         break;
  1288.  
  1289.       case HKO_BY_TITLE|HKO_PATTERN:
  1290.         screen = ScreenByTitle(opt->ArgStr[0]);
  1291.         break;
  1292.             
  1293.       case HKO_REARMOST:
  1294.         screen = RearmostScreen();
  1295.         break;
  1296.  
  1297.       case HKO_FRONTMOST:
  1298.         screen = FrontmostScreen();
  1299.         break;
  1300.     }
  1301.  
  1302.     return screen;
  1303. }
  1304.  
  1305.  
  1306. static void
  1307. ChangeScreen(YakOption *opt)
  1308. {
  1309.     struct Screen *scr;
  1310.     char *scrname;
  1311.  
  1312.     if (!(opt->Flags & HKO_NO_SCREEN_CHANGE))
  1313.         {
  1314.                 switch (opt->Flags)
  1315.                 {
  1316.                   case HKO_WORKBENCH_TO_FRONT:
  1317.                         scrname = "Workbench";
  1318.                         break;
  1319.  
  1320.                   case HKO_DEFAULT_PUBSCR_TO_FRONT:
  1321.                         scrname = NULL;
  1322.                         break;
  1323.                 }
  1324.  
  1325.                 if (scr = LockPubScreen(scrname))
  1326.                 {
  1327.                         ScreenToFront(scr);
  1328.                         UnlockPubScreen(NULL, scr);
  1329.                 }
  1330.         }
  1331. }
  1332.  
  1333.  
  1334. /*
  1335.  * the generic hotkey action stub
  1336.  */
  1337. void
  1338. PerformAction(YakHotKey *yhk)
  1339. {
  1340.     /* and perform action (gobbledegook!? that's C for you...) */
  1341.     (*(yhktypes[yhk->yhk_Type].yhkt_Command))(yhk);
  1342. }
  1343.  
  1344.